#include "inc/crc32_ieee.h"

CRC32IEEE::CRC32IEEE()
{
    m_name = "CRC32/IEEE";
    m_pascal = "x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1";
    m_poly = 0x04C11DB7;
    m_init = 0xFFFFFFFF;
    m_xorout = 0xFFFFFFFF;
    m_refin = true;
    m_refout = true;
}

uint64_t CRC32IEEE::crcCalc(const uint8_t *data, int64_t len)
{
    if (NULL == data) {
        return -1;
    }
    if (len <= 0) {
        return -1;
    }

    uint32_t crc = 0x00000000;

    static const uint32_t table[16] = {
        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
    };

    crc = ~crc;

    for (int64_t i = 0; i < len; i++) {
        uint8_t byte = data[i];

        crc = (crc >> 4) ^ table[(crc ^ byte) & 0x0f];
        crc = (crc >> 4) ^ table[(crc ^ (byte >> 4)) & 0x0f];
    }

    return (~crc);
}
